#include <array>
#include <iostream>

using namespace std;

#define ON  if (1)
#define OFF if (0)
#define N   10
#define OUT(arr, msg) do{ \
    cout << msg; \
    for (size_t i = 0; i < arr.size(); i++) cout << arr[i] << " "; \
    cout << endl; \
}while(0)

int main(int argc, char const *argv[])
{
    /*****************************************************************************************************
     * array序列容器
     * ---------------------------------------------------------------------------------------------------
     * 头文件  <array>
     * array序列容器可以理解为在普通数组基础上，增加了一些成员函数和全局函数
     * 它比普通数组要安全， 但效率并没有因此降低
     *****************************************************************************************************/
    // -----------------------------------------------
    // --- 定义 ----
    // -----------------------------------------------

    OFF
    {
        // 默认定义序列容器不会初始化， 如下定义会出输出乱值
        array<int, N> nums; 
        OUT(nums, "未初始化的array序列: ");
    }
    
    OFF
    {
        // 这样定义会初始化为0
        array<float, N> nums{};
        OUT(nums, "默认初始化array序列: ");
    }
    
    OFF
    {
        // 局部初始化定义
        array<float, N> nums{2.3, 2.4, 4};
        OUT(nums, "局部初始化array序列: ");
    }

    /*****************************************************************************************************
     * array序列的成员函数
     * ---------------------------------------------------------------------------------------------------
     * ********** 返回迭代器 **********
     * 
     * array.begin()        返回:随机访问迭代器  首元素位置指针   
     * 
     * array.end()          返回:随机访问迭代器  末尾元素后面位置指针  
     * 
     * array.rbegin()       返回:随机访问迭代器  末尾元素位置指针, 反向迭代器  
     * 
     * array.rend()         返回:随机访问迭代器  首元素之前位置指针, 反向迭代器
     * 
     * array.cbegin()       返回:随机访问迭代器  首元素位置指针, 不能通过指针修改值
     * 
     * array.cend()         返回:随机访问迭代器  末尾元素后面位置指针, 不能通过指针修改值
     * 
     * array.crbegin()      返回:随机访问迭代器  末尾元素位置指针, 反向迭代器, 不能通过指针修改值  
     * 
     * array.crend()        返回:随机访问迭代器  首元素之前位置指针, 反向迭代器, 不能通过指针修改值
     * 
     * 
     * ********** 容量 **********
     * 
     * array.size() 	    返回: array中元素个数
     * 
     * array.max_size() 	返回: array可容纳最大个数, 在array中, size和max_size始终是相等的。
     * 
     * array.empty() 	    返回: 元素个数是否为0
     * 
     * 
     * 
     * ********** 访问成员 **********
     * array[]              使用 [] 操作符可以直接访问对应下标的成员
     * 
     * array.at(n) 	        返回: 容器中 n 位置处元素的引用，该函数自动检查 n 是否在有效的范围内，如果不是则抛出 out_of_range 异常。
     * 
     * array.front() 	    返回: 容器中第一个元素的直接引用，该函数不适用于空的 array 容器。
     * 
     * array.back()         返回容器中最后一个元素的直接应用，该函数同样不适用于空的 array 容器。
     * 
     * array.data()         返回一个指向容器首个元素的指针。利用该指针，可实现复制容器中所有元素等类似功能。
     * 
     * ********** 修改成员 **********
     * 
     * array.fill(val)      使用val填充整个array
     * 
     * array1.swap(array2) 	交换 array1 和 array2 容器中的所有元素，但前提是它们具有相同的长度和类型。
     *****************************************************************************************************/

    // array.begin() 
    // -----------------------------------------------
    OFF
    {
        array<int, N> nums{50, 10, 40, 20, 60, 70, 100, 80, 90, 30};
        int *p = nums.begin();
        OUT(nums, "序列: ");
        cout << "array.begin() 位置的元素: " << *p << endl;
    }

    // array.end()
    // -----------------------------------------------
    OFF
    {
        array<int, N> nums{50, 10, 40, 20, 60, 70, 100, 80, 90, 30};
        OUT(nums, "序列: ");
        int *p = nums.end();
        p--;
        cout << "array.end() 之前位置的元素: " << *p << endl;

        cout << "结合使用迭代器 begin 和 end 遍历array: " << endl;
        for (int *i = nums.begin(); i < nums.end(); i++) 
            cout << *i << " ";
        cout << endl;
    }

    // array.rbegin()
    // -----------------------------------------------
    OFF
    {
        array<int, N> nums{50, 10, 40, 20, 60, 70, 100, 80, 90, 30};
        OUT(nums, "序列: ");
        // 注意， r开头的迭代器函数返回值类型是反向迭代器类型， reverse_iterator
        // 反向迭代器的 + 和 - 操作与正常的指针操作都是相反的
        reverse_iterator<int *> q = nums.rbegin();
        cout << "array.rbegin() 位置的元素" << *(q) << endl;
    }

    // array.rend()
    // -----------------------------------------------
    OFF
    {
        array<int, N> nums{50, 10, 40, 20, 60, 70, 100, 80, 90, 30};
        OUT(nums, "序列: ");
        reverse_iterator<int *> q = nums.rend();
        q--;
        cout << "array.rend() 之前位置的元素: " << *q << endl;
    }

    // array.cbegin() 
    // -----------------------------------------------
    OFF
    {
        array<int, N> nums{50, 10, 40, 20, 60, 70, 100, 80, 90, 30};
        OUT(nums, "序列: ");
        // 指针位置与 begin() 相同， 不同在于增加了const属性， 不能通过指针修改值
        const int * p = nums.cbegin();
        cout << "array.cbegin() 位置的元素: " << *p << endl;
    }

    // array.cend() 
    // -----------------------------------------------
    OFF
    {
        array<int, N> nums{50, 10, 40, 20, 60, 70, 100, 80, 90, 30};
        OUT(nums, "序列: ");
        // 指针位置与 end() 相同， 不同在于增加了const属性， 不能通过指针修改值
        const int *p = nums.cend();
        p--;
        cout << "array.cend() 之前位置的元素: " << *p << endl;
    }
    

    // array.crbegin()
    // -----------------------------------------------
    OFF
    {
        array<int, N> nums{50, 10, 40, 20, 60, 70, 100, 80, 90, 30};
        OUT(nums, "序列: ");
        // 指针位置与 rbegin() 相同， 不同在于增加了const属性， 不能通过指针修改值
        // 注意， r开头的迭代器函数返回值类型是反向迭代器类型， reverse_iterator
        // 反向迭代器的 + 和 - 操作与正常的指针操作都是相反的
        reverse_iterator<const int *> p = nums.crbegin();
        cout << "array.crbegin() 位置的元素" << *p << endl;
    }
    

    // array.crend()
    // -----------------------------------------------
    OFF
    {
        array<int, N> nums{50, 10, 40, 20, 60, 70, 100, 80, 90, 30};
        OUT(nums, "序列: ");
        // 指针位置与 rend() 相同， 不同在于增加了const属性， 不能通过指针修改值
        reverse_iterator<const int *> p = nums.crend();
        p--;
        cout << "array.crend() 位置移动一位之后的的元素: " << *p << endl;
    }
    


    // array.size()
    // -----------------------------------------------
    ON
    {
        array<int, N> nums{50, 10, 40, 20};
        OUT(nums, "序列: ");
        cout << "array.size() : " << nums.size() << endl;
    }

    // array.max_size()
    // -----------------------------------------------
    OFF
    {
        array<int, N> nums{50, 10, 40, 20, 60, 70, 100, 80, 90, 30};
        OUT(nums, "序列: ");
        cout << "array.max_size() : " << nums.max_size() << endl;
    }
    


    // array.empty()
    // -----------------------------------------------
    // 这个值和 (array.size() == 0)返回的是相同的， 但是，使用empty效率会更高
    OFF
    {
        array<int, 0> empty_arr{};
        cout << "array<int, 0> empty_arr{}" << endl;
        cout << "array.empty() : " << empty_arr.empty() << endl;
        array<int, N> nums{};
        OUT(nums, "序列: ");
         cout << "array.empty() : " << nums.empty() << endl;
    }
    


    // array.at(n)
    // -----------------------------------------------
    OFF
    {
        array<int, N> nums{50, 10, 40, 20, 60, 70, 100, 80, 90, 30};
        OUT(nums, "序列: ");
        // at中返回的元素是array[下标]号元素
        cout << "array.at(5) : " << nums.at(5) << endl;
    }
    


    // array.fill()
    // -----------------------------------------------
    OFF
    {
        array<int, N> nums{};
        OUT(nums, "序列: ");
        nums.fill(7);
        OUT(nums, "array.fill(7) : ");
    }
    

    return 0;
}
